home *** CD-ROM | disk | FTP | other *** search
- ////////////////////////////////////////////////////////////////////////////////
- //
- // uBrowser - a program that illustrates one way of embedding the
- // Mozilla Gecko (tm) Rendering Engine in an application, grabbing the
- // rendered output and displaying it on the surface of a 3D polygon as
- // texture in an OpenGL (tm) application.
- //
- // uBrowser is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2 of the License, or
- // (at your option) any later version.
- //
- // uBrowser is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with uBrowser; if not, write to the Free Software
- // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- //
- // Original code: Copyright 2005 Linden Research Inc.
- // http://www.lindenlab.com
- //
- // Primary author and site maintainer: Callum Prentice (callum@ubrowser.com)
- //
- // See contributors.txt or http://ubrowser.com for a list of contributors
- // without whose generous donation of time and effort, this application
- // would not have been possible.
- //
- ////////////////////////////////////////////////////////////////////////////////
- #include "ubrowser.h"
-
- #ifdef _WINDOWS
- #include <windows.h>
- #endif
-
- #include <iostream>
- #include <sstream>
- #include <time.h>
-
- // connects GLUI callbacks to the app class
- uBrowser* gInstance = 0;
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- uBrowser::uBrowser() :
- mName( "uBrowser - version 1.0.4" ),
- mBrowserWindowWidth( 800 ),
- mBrowserWindowHeight( 800 ),
- mTextureWidth( 0 ),
- mTextureHeight( 0 ),
- mTextureScaleX( 0.0f ),
- mTextureScaleY( 0.0f ),
- mViewportAspect( 0.0f ),
- mIdReset( 0x0010 ),
- mIdBookmarks( 0x0011 ),
- mIdExit( 0x0012 ),
- mIdTypeNull( 0x0013 ),
- mIdTypeFlat( 0x0014 ),
- mIdTypeBall( 0x0015 ),
- mIdTypeCube( 0x0016 ),
- mIdTypeFlag( 0x0017 ),
- mIdUrlEdit( 0x0018 ),
- mIdNavBack( 0x0019 ),
- mIdNavStop( 0x001a ),
- mIdNavHome( 0x001b ),
- mIdNavForward( 0x001c ),
- mIdBrowserSmall( 0x001d ),
- mIdBrowserMedium( 0x001e ),
- mIdBrowserLarge( 0x001f ),
- mFocusUrlEdit( 0x0020 ),
- mStatusText( 0 ),
- mProgressText( 0 ),
- mHomeUrl( "http://www.secondlife.com" )
- {
- // use this to connect GLUI callbacks to this class
- gInstance = this;
-
- // list of bookmarks that demonstrate cool stuff!
- mBookmarks.push_back( std::pair< std::string, std::string >( "Select a bookmark", "" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "Second Life Home Page", "http://www.secondlife.com" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "Mozilla Home Page", "http://www.mozilla.org" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "Google Home", "http://www.google.com" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "Google Maps", "http://maps.google.com" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "Boing Boing", "http://www.boingboing.net" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "Digg", "http://www.digg.com" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "Yahoo! User Interface Library slider", "http://developer.yahoo.net/yui/slider/examples/slider.html" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "Canvascape", "http://www.abrahamjoffe.com.au/ben/canvascape/" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "SVG Tetris (arrow keys and spacebar)", "http://www.croczilla.com/svg/samples/svgtetris/svgtetris.svg" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "SVG Opacity & Hover", "http://www.croczilla.com/svg/samples/opacity1/opacity1.xml" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "SVG Interactive lines", "http://www.croczilla.com/svg/samples/xbl-shapes2/xbl-shapes2.xml" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "SVG Interactive shapes", "http://www.croczilla.com/svg/samples/xbl1/xbl1.xml" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "XUL SQL Viewer", "http://www.georgenava.com/xul/dineros/dineros.php" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "XUL Email App", "http://www.georgenava.com/xul/gmail/gmail.php" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "XUL Outliner App", "http://www.georgenava.com/xul/outliner/outliner.php" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "XUL Video Poker", "http://www.georgenava.com/xul/poker/videopoker.php" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "XUL Visual Designer Studio", "http://www.georgenava.com/xul/studio/visualdesigner.php" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "XUL Photo Viewer", "http://www.georgenava.com/xul/photo/photoviewer.php" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "XUL Widgets", "http://www.hevanet.com/acorbin/xul/top.xul" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "XUL Mozilla Amazon Browser (MAB)", "http://www.faser.net/mab/chrome/content/mab.xul" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "DHTML Lemmings!", "http://www.funnygames.nl/host/games/lemmings/" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "DHTML Demos", "http://www.dhteumeuleu.com/" ) );
- mBookmarks.push_back( std::pair< std::string, std::string >( "about:config", "about:config" ) );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- uBrowser::~uBrowser()
- {
- // clean up - don't generally get here since we quit from a GLUT app with exit..!!
- if ( mEmbeddedBrowser )
- {
- mEmbeddedBrowser->getBrowserWindow()->remObserver( this );
- delete mEmbeddedBrowser;
- };
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- bool uBrowser::init( const char* arg0, int appWindowIn )
- {
- // save the GLUT window handle since we need to reset it sometimes.
- // (GLUT/GLUI dependency)
- mAppWindow = appWindowIn;
-
- // build GUI
- makeChrome();
-
- glClearColor( 0.0f, 0.0f, 0.0f, 0.5f );
- glClearDepth( 1.0f );
- glEnable( GL_DEPTH_TEST );
- glDepthFunc( GL_LEQUAL );
- glEnable( GL_TEXTURE_2D );
-
- // create the red/blue texture used in picking
- glGenTextures( 1, &mRedBlueTexture );
- for( int y = 0; y < 256; ++y )
- {
- for( int x = 0; x < 256 * 3 ; x += 3 )
- {
- mRedBlueTexturePixels[ y * 256 * 3 + x + 0 ] = ( x / 3 );
- mRedBlueTexturePixels[ y * 256 * 3 + x + 1 ] = 0;
- mRedBlueTexturePixels[ y * 256 * 3 + x + 2 ] = y;
- };
- }
- glBindTexture( GL_TEXTURE_2D, mRedBlueTexture );
- glTexImage2D( GL_TEXTURE_2D, 0,
- GL_RGB,
- 256, 256,
- 0, GL_RGB, GL_UNSIGNED_BYTE, mRedBlueTexturePixels );
-
- // create the green texture used in picking
- glGenTextures( 1, &mGreenTexture );
- for( int i = 0; i < 16 * 16 * 3; i += 3 )
- {
- mGreenTexturePixels[ i + 0 ] = 0;
- mGreenTexturePixels[ i + 1 ] = ( unsigned char )( i / 3 );
- mGreenTexturePixels[ i + 2 ] = 0;
- }
- glBindTexture( GL_TEXTURE_2D, mGreenTexture );
- glTexImage2D( GL_TEXTURE_2D, 0,
- GL_RGB,
- 16, 16,
- 0, GL_RGB, GL_UNSIGNED_BYTE, mGreenTexturePixels );
-
- // create the texture used to display the browser data
- glGenTextures( 1, &mAppTexture );
- glBindTexture( GL_TEXTURE_2D, mAppTexture );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- glTexImage2D( GL_TEXTURE_2D, 0,
- GL_RGB,
- mTextureWidth, mTextureHeight,
- 0, GL_RGB, GL_UNSIGNED_BYTE, 0 );
-
- resetView();
-
- // start with the flat rectangle so we don't freak people out :)
- mCurObjType = mIdTypeFlat;
-
- // make and initialise the embedded browser
- mEmbeddedBrowser = new embeddedBrowser;
- if ( mEmbeddedBrowser )
- {
- // need a native window handle
- void* nativeWindow = getNativeWindowHandle();
-
- // in the example, pass in the value of argv[ 0 ] as the base dir
- std::string appBaseDir = std::string( arg0 ).substr( 0, std::string( arg0 ).find_last_of("\\/") );
-
- if ( mEmbeddedBrowser->init( appBaseDir, mBrowserWindowWidth, mBrowserWindowHeight ) )
- {
- mEmbeddedBrowser->createWindow( nativeWindow );
-
- // observer events on it like status text changes and progress
- if ( mEmbeddedBrowser->getBrowserWindow() )
- mEmbeddedBrowser->getBrowserWindow()->addObserver( this );
-
- setSize( mBrowserWindowWidth, mBrowserWindowHeight );
-
- mEmbeddedBrowser->navigateTo( mHomeUrl.c_str() );
- }
- else
- {
- return false;
- };
- }
- else
- {
- return false;
- };
-
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- bool uBrowser::reset()
- {
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::reshape( int widthIn, int heightIn )
- {
- // save these as we'll need them later
- mWindowWidth = widthIn;
- mWindowHeight = heightIn;
-
- // just a rough calculation
- mUrlEdit->set_w( mWindowWidth - 400 );
- mStatusText->set_w( mWindowWidth - 100 );
-
- // update viewport (the active window inside the chrome stuff)
- int viewportX, viewportY;
- int viewportHeight, viewportWidth;
- GLUI_Master.get_viewport_area( &viewportX, &viewportY, &viewportWidth, &viewportHeight );
- glViewport( viewportX, viewportY, viewportWidth, viewportHeight );
-
- // need this when we come to display
- mViewportAspect = ( float )( viewportWidth ) / ( float)( viewportHeight );
-
- // GLUI requires this
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- // trigger re-display
- glutPostRedisplay();
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::drawGeometry( int typeIn )
- {
- // plain old flat rectangle
- if ( typeIn == mIdTypeFlat )
- {
- glColor3f( 1.0f, 1.0f, 1.0f );
- glBegin( GL_QUADS );
- glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, 0.0f );
- glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, 0.0f );
- glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, 0.0f );
- glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f, 1.0f, 0.0f );
- glEnd();
- }
- else
- // a ball - just because you can :) draw my own ball since the glu/glut ones don't get me
- // enough control over the texture coordinate details
- if ( typeIn == mIdTypeBall )
- {
- // this is based on some code from here: http://astronomy.swin.edu.au/~pbourke/opengl/sphere/
- const int numElems = 40;
- const GLfloat piDiv2 = 1.57079632679489661923f;
- const GLfloat piMul2 = 6.28318530717958647692f;
-
- for( int j = 0; j < numElems / 2; ++j )
- {
- GLfloat theta1 = j * ( piMul2 ) / numElems - piDiv2;
- GLfloat theta2 = ( j + 1 ) * ( piMul2 ) / numElems - piDiv2;
-
- glBegin( GL_TRIANGLE_STRIP );
-
- for( int i = 0; i <= numElems; i++ )
- {
- GLfloat theta3 = i * piMul2 / numElems;
-
- GLfloat pointX = cos( theta2 ) * cos( theta3 );
- GLfloat pointY = sin( theta2 );
- GLfloat pointZ = cos( theta2 ) * sin( theta3 );
-
- glNormal3f( pointX, pointY, pointZ );
- glTexCoord2f( i / ( GLfloat )numElems, 2 * ( j + 1 ) / ( GLfloat )numElems );
- glVertex3f( pointX, pointY, pointZ );
-
- pointX = cos( theta1 ) * cos( theta3 );
- pointY = sin( theta1 );
- pointZ = cos( theta1 ) * sin( theta3 );
-
- glNormal3f( pointX, pointY, pointZ );
- glTexCoord2f( i / ( GLfloat )numElems, 2 * j / ( GLfloat )numElems);
- glVertex3f( pointX, pointY, pointZ );
- };
- glEnd();
- };
- }
- else
- // same browser on all six faces - of course, what really should happen is one on each face
- // but that's for later
- if ( typeIn == mIdTypeCube )
- {
- const GLfloat delta = 0.75f;
-
- glColor3f( 1.0f, 1.0f, 1.0f );
- glBegin( GL_QUADS );
- glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -delta, -delta, -delta );
- glTexCoord2f( 1.0f, 0.0f ); glVertex3f( delta, -delta, -delta );
- glTexCoord2f( 1.0f, 1.0f ); glVertex3f( delta, delta, -delta );
- glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -delta, delta, -delta );
-
- glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -delta, -delta, delta );
- glTexCoord2f( 0.0f, 1.0f ); glVertex3f( delta, -delta, delta );
- glTexCoord2f( 1.0f, 1.0f ); glVertex3f( delta, delta, delta );
- glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -delta, delta, delta );
-
- glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -delta, -delta, -delta );
- glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -delta, -delta, delta );
- glTexCoord2f( 1.0f, 1.0f ); glVertex3f( delta, -delta, delta );
- glTexCoord2f( 0.0f, 1.0f ); glVertex3f( delta, -delta, -delta );
-
- glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -delta, delta, -delta );
- glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -delta, delta, delta );
- glTexCoord2f( 1.0f, 1.0f ); glVertex3f( delta, delta, delta );
- glTexCoord2f( 1.0f, 0.0f ); glVertex3f( delta, delta, -delta );
-
- glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -delta, -delta, -delta );
- glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -delta, delta, -delta );
- glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -delta, delta, delta );
- glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -delta, -delta, delta );
-
- glTexCoord2f( 0.0f, 0.0f ); glVertex3f( delta, -delta, -delta );
- glTexCoord2f( 0.0f, 1.0f ); glVertex3f( delta, delta, -delta );
- glTexCoord2f( 1.0f, 1.0f ); glVertex3f( delta, delta, delta );
- glTexCoord2f( 1.0f, 0.0f ); glVertex3f( delta, -delta, delta );
- glEnd();
- }
- else
- // waving flag - again - not useful but it looks great..
- if ( typeIn == mIdTypeFlag )
- {
- // this is based on some code from here: http://nehe.gamedev.net
- const int resolution = 45;
- static GLfloat points[ resolution ][ resolution ][ 3 ];
- static int wiggle = 0;
- static bool init = false;
-
- if ( ! init )
- {
- for( int x = 0; x < resolution; x++ )
- {
- for( int y = 0; y < resolution; y++ )
- {
- points[ x ][ y ][ 0 ] = ( GLfloat )( ( x / ( ( GLfloat )( resolution ) / 2.0f ) ) - 1.0f );
- points[ x ][ y ][ 1 ] = ( GLfloat )( ( y / ( ( GLfloat )( resolution ) / 2.0f ) ) - 1.0f );
- points[ x ][ y ][ 2 ] = ( GLfloat )( cos ( ( ( ( ( x + y ) / 5.0f ) * 40.0f ) / 360.0f ) * 3.141592654 * 2.0f ) * 0.1f );
- };
- };
- init = true;
- };
-
- glColor3f( 1.0f, 1.0f, 1.0f );
- glBegin( GL_QUADS );
- for( int x = 0; x < resolution - 1; x++ )
- {
- for( int y = resolution - 2; y > -1; --y )
- {
- int xCoord1 = x;
- int yCoord1 = y;
-
- int xCoord2 = x;
- int yCoord2 = y + 1;
-
- int xCoord3 = x + 1;
- int yCoord3 = y + 1;
-
- int xCoord4 = x + 1;
- int yCoord4 = y;
-
- glTexCoord2f( ( GLfloat )( xCoord1 ) / ( GLfloat )( resolution - 1 ),
- ( GLfloat )( yCoord1 ) / ( GLfloat )( resolution - 1 ) );
- glVertex3f( points[ xCoord1 ][ yCoord1 ][ 0 ], points[ xCoord1 ][ yCoord1 ][ 1 ], points[ xCoord1 ][ yCoord1 ][ 2 ] );
-
- glTexCoord2f( ( GLfloat )( xCoord2 ) / ( GLfloat )( resolution - 1 ),
- ( GLfloat )( yCoord2 ) / ( GLfloat )( resolution - 1 ) );
- glVertex3f( points[ xCoord2 ][ yCoord2 ][ 0 ], points[ xCoord2 ][ yCoord2 ][ 1 ], points[ xCoord2 ][ yCoord2 ][ 2 ] );
-
- glTexCoord2f( ( GLfloat )( xCoord3 ) / ( GLfloat )( resolution - 1 ),
- ( GLfloat )( yCoord3 ) / ( GLfloat )( resolution - 1 ) );
- glVertex3f( points[ xCoord3 ][ yCoord3 ][ 0 ], points[ xCoord3 ][ yCoord3 ][ 1 ], points[ xCoord3 ][ yCoord3 ][ 2 ] );
-
- glTexCoord2f( ( GLfloat )( xCoord4 ) / ( GLfloat )( resolution - 1 ),
- ( GLfloat )( yCoord4 ) / ( GLfloat )( resolution - 1 ) );
- glVertex3f( points[ xCoord4 ][ yCoord4 ][ 0 ], points[ xCoord4 ][ yCoord4 ][ 1 ], points[ xCoord4 ][ yCoord4 ][ 2 ] );
- };
- };
- glEnd();
-
- if ( ++wiggle == 3 )
- {
- for( int y = 0; y < resolution; ++y )
- {
- GLfloat swap = points[ 0 ][ y ][ 2 ];
- for( int x = 0; x < ( resolution - 1 ); ++x )
- {
- points[ x ][ y ][ 2 ] = points[ x + 1 ][ y ][ 2 ];
- };
- points[ resolution - 1 ][ y ][ 2 ] =swap;
- };
- wiggle = 0;
- };
- };
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::display()
- {
- // let's start with a clean slate
- glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
- // scale all texture so that they fit the geometry exactly
- glMatrixMode( GL_TEXTURE );
- glPushMatrix();
- glScalef( mTextureScaleX, mTextureScaleY, 1.0f );
-
- // set up OpenGL view
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
- glFrustum( -mViewportAspect * 0.04f, mViewportAspect * 0.04f, -0.04f, 0.04f, 0.1f, 50.0f );
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
- glTranslatef( 0.0, 0.0, -3.0f );
- glTranslatef( mViewPos[ 0 ], mViewPos[ 1 ], -mViewPos[ 2 ] );
- glMultMatrixf( mViewRotation );
- glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );
- glScalef( 1.0f, 1.0f, 1.0f );
-
- // red blue pattern
- glBindTexture( GL_TEXTURE_2D, mRedBlueTexture );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
- drawGeometry( mCurObjType );
-
- // read colors and get red/blue value
- glReadPixels( mCurMouseX, mCurMouseY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, mPixelColorRB );
-
- // green texture mask
- glBindTexture( GL_TEXTURE_2D, mGreenTexture );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
- glMatrixMode( GL_TEXTURE );
- glPushMatrix();
- glScalef( mTextureScaleX * 256.0f, mTextureScaleX * 256.0f, 1.0f ); // scale the scale by the scale :)
- drawGeometry( mCurObjType );
- glPopMatrix();
- glMatrixMode( GL_MODELVIEW );
-
- // read colors and get green value
- glReadPixels( mCurMouseX, mCurMouseY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, mPixelColorG );
-
- // draw the browser texture
- glBindTexture( GL_TEXTURE_2D, mAppTexture );
-
- if ( mEmbeddedBrowser )
- {
- if ( mEmbeddedBrowser->getPageBuffer() )
- {
- glTexSubImage2D( GL_TEXTURE_2D, 0,
- 0, 0,
- // because sometimes the rowspan != width * bytes per pixel (mBrowserWindowWidth)
- mEmbeddedBrowser->getBrowserRowSpan() / mEmbeddedBrowser->getBrowserDepth(),
- mBrowserWindowHeight,
- mEmbeddedBrowser->getBrowserDepth() == 3 ? GL_BGR_EXT : GL_BGRA_EXT,
- GL_UNSIGNED_BYTE,
- mEmbeddedBrowser->getPageBuffer() );
- };
- };
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- drawGeometry( mCurObjType );
-
- // restore matrix after texture scale
- glMatrixMode( GL_TEXTURE );
- glPopMatrix();
-
- glutSwapBuffers();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::idle()
- {
- // use this to throttle updates
- clock_t currentTime = clock();
- static clock_t startTime = currentTime;
-
- // time to update page
- if ( ( currentTime - startTime ) > ( CLOCKS_PER_SEC / 50 ) )
- {
- // grab the contents of the rendered page
- mEmbeddedBrowser->grabWindow();
-
- // enable/disable back button depending on whether we can go back or not
- if ( mEmbeddedBrowser->canNavigateBack() )
- mNavBackButton->enable();
- else
- mNavBackButton->disable();
-
- // enable/disable back button depending on whether we can go back or not
- if ( mEmbeddedBrowser->canNavigateForward() )
- mNavForwardButton->enable();
- else
- mNavForwardButton->disable();
-
- // reset timer
- startTime = currentTime;
- };
-
- // GLUI needs this
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- // lots of updates for smooth motion
- glutPostRedisplay();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::resetView()
- {
- mViewRotationCtrl->reset();
-
- mViewScaleCtrl->set_x( 0.0f );
- mViewScaleCtrl->set_y( 0.0f );
- mViewScaleCtrl->set_z( 0.0f );
-
- mViewTranslationCtrl->set_x( 0.0f );
- mViewTranslationCtrl->set_y( 0.0f );
- mViewTranslationCtrl->set_z( 0.0f );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::makeChrome()
- {
- // top UI bar
- mTopGLUIWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
-
- mNavBackButton = mTopGLUIWindow->add_button( "<<<", mIdNavBack, gluiCallbackWrapper );
- mNavBackButton->set_w( 56 );
-
- mTopGLUIWindow->add_column( false );
- GLUI_Button* button = mTopGLUIWindow->add_button( "STOP", mIdNavStop, gluiCallbackWrapper );
- button->set_w( 56 );
-
- mTopGLUIWindow->add_column( false );
- button = mTopGLUIWindow->add_button( "HOME", mIdNavHome, gluiCallbackWrapper );
- button->set_w( 56 );
-
- mTopGLUIWindow->add_column( false );
- mNavForwardButton = mTopGLUIWindow->add_button( ">>>", mIdNavForward, gluiCallbackWrapper );
- mNavForwardButton->set_w( 56 );
-
- mTopGLUIWindow->add_column( false );
- mUrlEdit = mTopGLUIWindow->add_edittext( "Url:", GLUI_EDITTEXT_TEXT, mNavUrl, mIdUrlEdit, gluiCallbackWrapper );
-
- mTopGLUIWindow->add_column( false );
- mTopGLUIWindow->add_button( "Focus", mFocusUrlEdit, gluiCallbackWrapper );
-
- mTopGLUIWindow->set_main_gfx_window( mAppWindow );
-
- // top UI bar (second part)
- mTop2GLUIWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
-
- mTop2GLUIWindow->add_column( false );
- GLUI_Listbox* bookmarkList = mTop2GLUIWindow->add_listbox( "Bookmarks", &mSelBookmark, mIdBookmarks, gluiCallbackWrapper );
- for( unsigned int each = 0; each < mBookmarks.size(); ++each )
- {
- bookmarkList->add_item( each, const_cast< char* >( mBookmarks[ each ].first.c_str() ) );
- };
- mTop2GLUIWindow->set_main_gfx_window( mAppWindow );
-
- // bottom UI bar
- mBottomGLUIWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_BOTTOM );
-
- mStatusText = mBottomGLUIWindow->add_statictext( "" );
-
- mBottomGLUIWindow->add_column( false );
- mProgressText = mBottomGLUIWindow->add_statictext( "" );
- mProgressText->set_alignment( GLUI_ALIGN_RIGHT );
-
- mBottomGLUIWindow->set_main_gfx_window( mAppWindow );
-
- // right side UI bar
- mRightGLUIWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_RIGHT );
-
- GLUI_Listbox* objTypelist = mRightGLUIWindow->add_listbox( "Type", &mCurObjType );
- objTypelist->add_item( mIdTypeFlat, "Flat" );
- objTypelist->add_item( mIdTypeCube, "Cube" );
- objTypelist->add_item( mIdTypeBall, "Ball" );
- objTypelist->add_item( mIdTypeFlag, "Flag" );
- mRightGLUIWindow->add_statictext( "" );
-
- mViewRotationCtrl = mRightGLUIWindow->add_rotation( "Rotation", mViewRotation );
-
- mViewTranslationCtrl = mRightGLUIWindow->add_translation( "Translate", GLUI_TRANSLATION_XY, mViewPos );
- mViewTranslationCtrl->set_speed( 0.01f );
-
- mViewScaleCtrl = mRightGLUIWindow->add_translation( "Scale", GLUI_TRANSLATION_Z, &mViewPos[ 2 ] );
- mViewScaleCtrl->set_speed( 0.05f );
-
- mRightGLUIWindow->add_statictext( "" );
-
- mRightGLUIWindow->add_statictext( "" );
- button = mRightGLUIWindow->add_button( "Small", mIdBrowserSmall, gluiCallbackWrapper );
- button->set_w( 64 );
-
- button = mRightGLUIWindow->add_button( "Medium", mIdBrowserMedium, gluiCallbackWrapper );
- button->set_w( 64 );
-
- button = mRightGLUIWindow->add_button( "Large", mIdBrowserLarge, gluiCallbackWrapper );
- button->set_w( 64 );
-
- GLUI_StaticText* text = mRightGLUIWindow->add_statictext( "Browser window size" );
- text->set_alignment( GLUI_ALIGN_CENTER );
- mRightGLUIWindow->add_statictext( "" );
-
- mRightGLUIWindow->add_statictext( "" );
- button = mRightGLUIWindow->add_button( "Reset", mIdReset, gluiCallbackWrapper );
- button->set_w( 64 );
-
- mRightGLUIWindow->add_statictext( "" );
- button = mRightGLUIWindow->add_button( "Exit", mIdExit, gluiCallbackWrapper );
- button->set_w( 64 );
-
- mRightGLUIWindow->set_main_gfx_window( mAppWindow );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::windowPosToTexturePos( int winXIn, int winYIn, int& texXOut, int& texYOut )
- {
- // this is how we convert from the color in the textures draw in the first 2 passes to an
- // XY location in the coordinate space of the texture
- mCurMouseX = winXIn;
- mCurMouseY = mWindowHeight - winYIn; // opposite Ycoordinate systems..
-
- // red gives 0..255 on X and blue value gives 0.255 on Y
- // green divides each distrete value by 16 giving 256 * 16 (4096) resolution in each of X & Y
- texXOut = ( mPixelColorRB[ 0 ] * 16 + ( mPixelColorG[ 1 ] & 0x0f ) ) / ( 4096 / mTextureWidth );
- texYOut = ( mPixelColorRB[ 2 ] * 16 + ( mPixelColorG[ 1 ] >> 4 ) ) / ( 4096 / mTextureHeight );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::keyboard( unsigned char keyIn, int xIn, int yIn )
- {
- // pass on the keypress to Mozilla - will need something more sophisticated here one day
- if ( mEmbeddedBrowser )
- mEmbeddedBrowser->keyPress( keyIn );
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::passiveMouse( int xIn, int yIn )
- {
- // called when the mouse is moving and button isn't pressed
- int x, y;
- windowPosToTexturePos( xIn, yIn, x, y );
-
- if ( mEmbeddedBrowser )
- mEmbeddedBrowser->mouseMove( x, y );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::mouseButton( int button, int state, int xIn, int yIn )
- {
- int x, y;
- windowPosToTexturePos( xIn, yIn, x, y );
-
- if ( button == GLUT_LEFT_BUTTON )
- {
- if ( state == GLUT_DOWN )
- {
- // send event to mozilla
- mEmbeddedBrowser->mouseDown( x, y );
- }
- else
- if ( state == GLUT_UP )
- {
- // send event to mozilla
- mEmbeddedBrowser->mouseUp( x, y );
-
- // this seems better than sending focus on mouse down (still need to improve this)
- mEmbeddedBrowser->mouseUp( x, y );
- mEmbeddedBrowser->focusBrowser( true );
-
- // turn off the URL edit widget so it's "obvious" that you need to press focus to reenable it.
- // (focus restriction in GLUI i wasn't able to work around)
- mUrlEdit->disable();
- };
- };
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::mouseMove( int xIn , int yIn )
- {
- // called when mouse moves and button is down
- int x, y;
- windowPosToTexturePos( xIn, yIn, x, y );
-
- if ( mEmbeddedBrowser )
- mEmbeddedBrowser->mouseMove( x, y );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::setSize( int widthIn , int heightIn )
- {
- // text the embedded browser that things changed
- if ( mEmbeddedBrowser )
- mEmbeddedBrowser->setSize( widthIn, heightIn, true );
-
- // calculate the next power of 2 bigger than reqquested size for width and height
- for ( mTextureWidth = 1; mTextureWidth < widthIn; mTextureWidth <<= 1 )
- {
- };
-
- for ( mTextureHeight = 1; mTextureHeight < heightIn; mTextureHeight <<= 1 )
- {
- };
-
- // save the height and width
- mBrowserWindowWidth = widthIn;
- mBrowserWindowHeight = heightIn;
-
- // we scale all textures by this much so that they fit the geometry
- mTextureScaleX = ( GLfloat )mBrowserWindowWidth / ( GLfloat )mTextureWidth;
- mTextureScaleY = ( GLfloat )mBrowserWindowHeight / ( GLfloat )mTextureHeight;
-
- // delete the old texture handle and create a new one
- glBindTexture( GL_TEXTURE_2D, 0 );
- glDeleteTextures( 1, &mAppTexture );
- glGenTextures( 1, &mAppTexture );
- glBindTexture( GL_TEXTURE_2D, mAppTexture );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, mTextureWidth, mTextureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0 );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::gluiCallback( int controlIdIn )
- {
- if ( controlIdIn == mIdExit )
- {
- // clean up code - since GLUT doesn't let us exit the event loop, we'll do it here
- // to make sure it works (deleting the browser instance was a major problem before)
- if ( mEmbeddedBrowser )
- {
- mEmbeddedBrowser->getBrowserWindow()->remObserver( this );
- delete mEmbeddedBrowser;
- };
-
- // write something out to the GLUT console to indicate we're all done
- std::cout << "Application finished. Buh-bye!" << std::endl;
-
- // only way out with GLUT
- exit( 0 );
- }
- else
- if ( controlIdIn == mIdReset )
- {
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- resetView();
-
- glutPostRedisplay();
- }
- else
- if ( controlIdIn == mIdBrowserSmall )
- {
- setSize( 400, 400 );
-
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- glutPostRedisplay();
- }
- else
- if ( controlIdIn == mIdBrowserMedium )
- {
- setSize( 800, 800 );
-
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- glutPostRedisplay();
- }
- else
- if ( controlIdIn == mIdBrowserLarge )
- {
- setSize( 1024, 1024 );
-
- if ( glutGetWindow() != mAppWindow )
- glutSetWindow( mAppWindow );
-
- glutPostRedisplay();
- }
- else
- if ( controlIdIn == mIdNavBack )
- {
- mEmbeddedBrowser->navigateBack();
- }
- else
- if ( controlIdIn == mIdNavStop )
- {
- mEmbeddedBrowser->navigateStop();
- }
- else
- if ( controlIdIn == mIdNavHome )
- {
- mEmbeddedBrowser->navigateTo( mHomeUrl.c_str() );
- }
- else
- if ( controlIdIn == mIdNavForward )
- {
- mEmbeddedBrowser->navigateForward();
- }
- else
- if ( controlIdIn == mIdUrlEdit )
- {
- mEmbeddedBrowser->navigateTo( mUrlEdit->get_text() );
- }
- else
- if ( controlIdIn == mIdBookmarks )
- {
- mEmbeddedBrowser->navigateTo( mBookmarks[ mSelBookmark ].second.c_str() );
- }
- else
- // silly hack needed to get around a limitation of GLUI
- // I really need a callback when caret enters the edit field so I can do this automatically
- if ( controlIdIn == mFocusUrlEdit )
- {
- mUrlEdit->enable();
- mEmbeddedBrowser->focusBrowser( false );
- setFocusNativeWindow();
- };
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::onNavigateBegin( const EventType& eventIn )
- {
- // could do something here like start a throbber :)
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::onNavigateComplete( const EventType& eventIn )
- {
- // could do something here like stop a throbber :)
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::onUpdateProgress( const EventType& eventIn )
- {
- // observed event - page progress changes
- glutSetWindow( mBottomGLUIWindow->get_glut_window_id() );
-
- std::ostringstream conv;
- conv << "[" << eventIn.getPayload()->getPercentComplete() << "% loaded]";
- mProgressText->set_text( const_cast< char* >( conv.str().c_str() ) );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::onStatusTextChange( const EventType& eventIn )
- {
- // observed event - status text changes, either during load or when you mouse over a link or a script does it
- glutSetWindow( mBottomGLUIWindow->get_glut_window_id() );
-
- // NOTE: only display the first 100 chars since anything longer breaks the display of percent loaded
- // on the right hand side - normally, you'd want to use the whole thing.
- mStatusText->set_text( const_cast< char*>( eventIn.getPayload()->getStatusMsg().substr( 0, 100 ).c_str() ) );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::onLocationChange( const EventType& eventIn )
- {
- // observed event - URL location changes - e.g. when a site redirects somewhere else
- // (ought to check that this is the top frame or this will be wrong)
- glutSetWindow( mTopGLUIWindow->get_glut_window_id() );
-
- mUrlEdit->set_text( const_cast< char*>( eventIn.getPayload()->getCurrentUri().c_str() ) );
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void* uBrowser::getNativeWindowHandle()
- {
- // My implementation of the embedded browser needs a native window handle
- // Can't get this via GLUT so had to use this hack
- #ifdef _WINDOWS
- return FindWindow( NULL, mName.c_str() );
- #else
- return 0;
- #endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void uBrowser::setFocusNativeWindow()
- {
- // need to set focus to the browser window so that keyboard events work
- #ifdef _WINDOWS
- SetFocus( FindWindow( NULL, mName.c_str() ) );
- #else
- return;
- #endif
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- static void gluiCallbackWrapper( int controlIdIn )
- {
- // dispatch GLUI callbacks into my class cos I like it that way :)
- if ( gInstance )
- gInstance->gluiCallback( controlIdIn );
- }